package cn.flying.system.service.cm.impl;

import javax.annotation.Resource;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import cn.flying.base.common.constants.Constants;
import cn.flying.base.common.vo.TreeSelectInfo;
import cn.flying.base.common.vo.XmSelect;
import cn.flying.base.core.common.utils.Ft;
import cn.flying.system.common.enums.ResTypeEnum;
import cn.flying.system.common.enums.SeqTypeEnum;
import cn.flying.system.common.vo.MenuInfo;
import cn.flying.system.common.vo.ResTreeVo;
import cn.flying.system.common.vo.ResourceUrlVo;
import cn.flying.system.domain.cm.CmResource;
import cn.flying.system.domain.cm.CmResourceExample;
import cn.flying.system.domain.cm.CmResourceUrl;
import cn.flying.system.domain.cm.CmResourceUrlExample;
import cn.flying.system.domain.cm.CmUser;
import cn.flying.system.mapper.cm.CmResourceMapper;
import cn.flying.system.mapper.cm.CmResourceUrlMapper;
import cn.flying.system.service.cm.CmResourceService;
import cn.flying.system.service.cm.CmRoleService;
import cn.flying.system.service.cm.CmSeqService;
import cn.flying.system.service.cm.CmUserService;

/**
 * @description: 权限资源接口服务
 * @author: lvyong
 * @date: 2023年05月30日 00:36
 * @version: 1.0
 */
@Service
public class CmResourceServiceImpl implements CmResourceService {
    @Resource
    private CmResourceMapper cmResourceMapper;
    @Resource
    private CmResourceUrlMapper cmResourceUrlMapper;
    @Resource
    private CmSeqService cmSeqService;
    @Resource
    private CmUserService cmUserService;
    @Resource
    private CmRoleService cmRoleService;

    /**
     * 10000 固定为根节点
     */
    private static final String res_root = "10000";

    /**
     * 查询所有的菜单资源
     *
     * @param username
     * @return
     */
    @Override
    public List<MenuInfo> getPermsResource(String username) {
        CmResourceExample example = new CmResourceExample();
        CmResourceExample.Criteria criteria = example.createCriteria();

        //如果用户为admin，则跳过权限验证
        if (!Constants.ADMINISTRATOR.equals(username)) {
            CmUser cmUser = cmUserService.findUserByUsername(username);
            List<String> roles = cmRoleService.getUserRoleList(cmUser.getUserId()).stream().map(role -> role.getRoleId()).distinct().collect(Collectors.toList());
            List<String> resIds = cmRoleService.getRoleResourceListByRoles(roles).stream().map(p -> p.getResId()).distinct().collect(Collectors.toList());
            if (CollectionUtils.isEmpty(resIds)) {
                return new LinkedList<>();
            }
            criteria.andResIdIn(resIds);
        }
        List<String> stringList = new ArrayList<>();
        stringList.add(ResTypeEnum.RES_TYPE_MENU.getCode());
        stringList.add(ResTypeEnum.RES_TYPE_SYS.getCode());
        criteria.andTypeIn(stringList);

        example.setOrderByClause(" seq asc ");
        //获取菜单
        List<CmResource> resources = cmResourceMapper.selectByExample(example);

        //获取一级菜单
        List<MenuInfo> rootMenu = new LinkedList<>();
        MenuInfo menuInfo;
        for (CmResource resource : resources) {
            //10000 固定为根节点
            if (res_root.equals(resource.getParentId())) {
                menuInfo = new MenuInfo();
                BeanUtils.copyProperties(resource, menuInfo);
                menuInfo.setMenuId(resource.getResId());
                menuInfo.setMenuName(resource.getResName());
                rootMenu.add(menuInfo);
            }
        }

        //这个是遍历所有主菜单,分别获取所有主菜单的所有子菜单
        for (MenuInfo info : rootMenu) {
            //获取所有子菜单 递归
            List<MenuInfo> childrenList = getChildrenMenu(info.getMenuId(), resources);
            //子菜单集合
            info.setChildren(childrenList);
        }
        return rootMenu;
    }

    private List<MenuInfo> getChildrenMenu(String parentId, List<CmResource> list) {
        List<MenuInfo> childrenList = new LinkedList<>();
        MenuInfo menuInfo;
        for (CmResource resource : list) {
            if (parentId.equals(resource.getParentId())) {
                menuInfo = new MenuInfo();
                BeanUtils.copyProperties(resource, menuInfo);
                menuInfo.setMenuId(resource.getResId());
                menuInfo.setMenuName(resource.getResName());
                childrenList.add(menuInfo);
            }
        }
        //递归，遍历所有的子菜单
        for (MenuInfo info : childrenList) {
            info.setChildren(getChildrenMenu(info.getMenuId(), list));
        }

        //如果子菜单为空的话，那就说明某菜单下没有子菜单了，直接返回空,子菜单为空的话就不会继续迭代了
        if (childrenList != null && childrenList.size() == 0) {
            return null;
        }
        return childrenList;
    }

    /**
     * 加载菜单资源树
     *
     * @return
     */
    @Override
    public List<TreeSelectInfo> getMenuTree() {
        CmResourceExample example = new CmResourceExample();
        CmResourceExample.Criteria criteria = example.createCriteria();
        List<String> stringList = new ArrayList<>();
        stringList.add(ResTypeEnum.RES_TYPE_MENU.getCode());
        stringList.add(ResTypeEnum.RES_TYPE_SYS.getCode());
        criteria.andTypeIn(stringList);
        //获取菜单
        List<CmResource> menuList = cmResourceMapper.selectByExample(example);

        List<TreeSelectInfo> treeSelectInfos = menuList.stream().map(m -> {
            TreeSelectInfo treeSelectInfo = new TreeSelectInfo();
            treeSelectInfo.setId(m.getResId());
            treeSelectInfo.setPid(m.getParentId());
            treeSelectInfo.setName(m.getTitle());
            treeSelectInfo.setOpen(false);
            treeSelectInfo.setChecked(false);
            return treeSelectInfo;
        }).collect(Collectors.toList());

        List<TreeSelectInfo> infos = streamToTree(treeSelectInfos, "0");

        for (TreeSelectInfo info : infos) {
            if (!CollectionUtils.isEmpty(info.getChildren())) {
                info.setOpen(true);
            }
        }

        return infos;
    }

    private List<TreeSelectInfo> streamToTree(List<TreeSelectInfo> treeList, String parentId) {
        List<TreeSelectInfo> list = treeList.stream()
                // 过滤父节点
                .filter(parent -> parent.getPid().equals(parentId))
                // 把父节点children递归赋值成为子节点
                .map(child -> {
                    List<TreeSelectInfo> temp = streamToTree(treeList, child.getId());
                    if (!CollectionUtils.isEmpty(temp)) {
                        child.setChildren(temp);
                    }
                    return child;
                }).collect(Collectors.toList());
        return list;
    }

    /**
     * 获取资源treetable
     *
     * @return
     */
    @Override
    public List<CmResource> getResourceTreeTableList() {
        CmResourceExample example = new CmResourceExample();
        CmResourceExample.Criteria criteria = example.createCriteria();

        example.setOrderByClause(" res_id asc, seq asc ");
//        criteria.andTypeEqualTo(ResourcesTypeEnum.PERMISSIONS_TYPE_MENU.getType());
        //获取所有的资源菜单
        List<CmResource> list = cmResourceMapper.selectByExample(example);

//        //从根节点开始
//        List<ResTreeTableInfo> treeTableInfos = convertResourceToTreeTableInfo(list);
//
//        List<ResTreeTableInfo> tableInfos = setChildren(treeTableInfos, "root");

        return list;
    }

//    private List<ResTreeTableInfo> convertResourceToTreeTableInfo(List<CmResource> list) {
//        return list.stream().map(resource -> {
//            ResTreeTableInfo tableInfo = new ResTreeTableInfo();
//            tableInfo.setId(resource.getId());
//            tableInfo.setResId(resource.getResId());
//            tableInfo.setResName(resource.getResName());
//            tableInfo.setType(resource.getType());
//            tableInfo.setTitle(resource.getTitle());
//            tableInfo.setParentId(resource.getParentId());
//            tableInfo.setHref(resource.getHref());
//            tableInfo.setIcon(resource.getIcon());
//            tableInfo.setMid(resource.getMid());
//            tableInfo.setSeq(resource.getSeq());
//            tableInfo.setStatus(resource.getStatus());
//            tableInfo.setUpdatedBy(resource.getUpdatedBy());
//            tableInfo.setUpdatedTime(resource.getUpdatedTime());
//            return tableInfo;
//        }).collect(Collectors.toList());
//    }
//
//    private List<ResTreeTableInfo> setChildren(List<ResTreeTableInfo> list, String parentId) {
//        List<ResTreeTableInfo> tableInfos = list.stream()
//                // 过滤父节点
//                .filter(parent -> parentId.equals(parent.getParentId()))
//                // 递归赋值children
//                .map(child -> {
//                    List<ResTreeTableInfo> temp = setChildren(list, child.getResId());
//                    if (CollectionUtils.isEmpty(temp)) {
//                        child.setChildren(new ArrayList<>());
//                        child.setParent(false);
//                    } else {
//                        child.setChildren(temp);
//                        child.setParent(true);
//                    }
//                    return child;
//                })
//                .collect(Collectors.toList());
//        return tableInfos;
//    }


    /**
     * 查询资源url列表数据
     *
     * @param resId
     * @return
     */
    @Override
    public List<CmResourceUrl> getResourcePageUrlList(String resId) {
        if (Ft.String.isBlank(resId)) {
            return new ArrayList<>();
        }
        CmResourceUrlExample example = new CmResourceUrlExample();
        CmResourceUrlExample.Criteria criteria = example.createCriteria();
        criteria.andResIdEqualTo(resId);
        return cmResourceUrlMapper.selectByExample(example);
    }

    /**
     * 查询资源信息
     *
     * @param resId
     * @return
     */
    @Override
    public CmResource getResourceByResId(String resId) {
        CmResourceExample example = new CmResourceExample();
        CmResourceExample.Criteria criteria = example.createCriteria();
        criteria.andResIdEqualTo(resId);
        List<CmResource> list = cmResourceMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.get(0);
    }

    /**
     * 根据ID查询资源信息
     *
     * @param id
     * @return
     */
    @Override
    public CmResource getResourceById(Long id) {
        return cmResourceMapper.selectByPrimaryKey(id);
    }

    /**
     * 资源菜单下拉树形结构
     *
     * @return
     */
    @Override
    public List<XmSelect> getResourceSelectList() {
        CmResourceExample example = new CmResourceExample();
        CmResourceExample.Criteria criteria = example.createCriteria();
        //获取组织
        List<CmResource> organizations = cmResourceMapper.selectByExample(example);

        List<XmSelect> xmSelects = organizations.stream().map(m -> {
            XmSelect xmSelect = new XmSelect();
            xmSelect.setValue(m.getResId());
            xmSelect.setName(m.getTitle());
            xmSelect.setPid(m.getParentId());
            xmSelect.setDisabled(false);
            xmSelect.setSelected(false);
            return xmSelect;
        }).collect(Collectors.toList());

        List<XmSelect> infos = listToTree(xmSelects, "root");

        return infos;
    }

    private List<XmSelect> listToTree(List<XmSelect> treeList, String parentId) {
        List list = treeList.stream()
                // 过滤父节点
                .filter(parent -> parent.getPid().equals(parentId))
                // 把父节点children递归赋值成为子节点
                .map(child -> {
                    List<XmSelect> temp = listToTree(treeList, child.getValue());
//                    if (!CollectionUtils.isEmpty(temp)) {
                    child.setChildren(temp);
//                    }
                    return child;
                }).collect(Collectors.toList());
        return list;
    }

    /**
     * 加载ztree 资源树形结构
     *
     * @return
     */
    @Override
    public List<ResTreeVo> getResourceTree() {
        CmResourceExample example = new CmResourceExample();
        CmResourceExample.Criteria criteria = example.createCriteria();
//        criteria.andTypeEqualTo(ResourcesTypeEnum.PERMISSIONS_TYPE_MENU.getType());
        //获取菜单
        List<CmResource> menuList = cmResourceMapper.selectByExample(example);

        List<ResTreeVo> trees = new ArrayList<>();
        ResTreeVo tree;
        for (CmResource resource : menuList) {
            tree = new ResTreeVo();
            tree.setResId(resource.getResId());
            tree.setTitle(resource.getTitle());
            tree.setParentId(resource.getParentId());
//            tree.setLevel(resource.getLevel());
            trees.add(tree);
        }
        return trees;
    }

    /**
     * 保存资源信息
     *
     * @param resource
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void insertResource(ResourceUrlVo resource) {
        String seq = cmSeqService.getSeq(SeqTypeEnum.MENU.name());
        CmResource cmResource = new CmResource();
        cmResource.setResId(seq);
        cmResource.setResName(resource.getResName());
        cmResource.setType(resource.getType());
        cmResource.setTitle(resource.getTitle());
        cmResource.setParentId(resource.getParentId());
        cmResource.setHref(resource.getHref());
        cmResource.setLevel(resource.getLevel());
        cmResource.setIcon(resource.getIcon());
        cmResource.setMid(resource.getMid());
        cmResource.setSeq(resource.getSeq());
        cmResource.setStatus(resource.getStatus());

        List<CmResourceUrl> cmResourceUrls = resource.getResUrls();

        for (CmResourceUrl cmResourceUrl : cmResourceUrls) {
            cmResourceUrl.setResId(cmResource.getResId());
            cmResourceUrlMapper.insert(cmResourceUrl);
        }

        cmResourceMapper.insertSelective(cmResource);
    }

    /**
     * 更新资源信息
     *
     * @param resource
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateResource(ResourceUrlVo resource) {
        CmResource cmResource = new CmResource();
        cmResource.setId(resource.getId());
        cmResource.setResId(resource.getResId());
        cmResource.setResName(resource.getResName());
        cmResource.setType(resource.getType());
        cmResource.setTitle(resource.getTitle());
        cmResource.setParentId(resource.getParentId());
        cmResource.setHref(resource.getHref());
        cmResource.setLevel(resource.getLevel());
        cmResource.setIcon(resource.getIcon());
        cmResource.setMid(resource.getMid());
        cmResource.setSeq(resource.getSeq());
        cmResource.setStatus(resource.getStatus());

        List<CmResourceUrl> cmResourceUrls = resource.getResUrls();

        //先删除原来所有的从新插入
        CmResourceUrlExample example = new CmResourceUrlExample();
        CmResourceUrlExample.Criteria criteria = example.createCriteria();
        criteria.andResIdEqualTo(cmResource.getResId());
        cmResourceUrlMapper.deleteByExample(example);

        for (CmResourceUrl cmResourceUrl : cmResourceUrls) {
            cmResourceUrlMapper.insert(cmResourceUrl);
        }

        cmResourceMapper.updateByPrimaryKeySelective(cmResource);
    }

    /**
     * 更新资源信息
     *
     * @param resource
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateResourceById(CmResource resource) {
        cmResourceMapper.updateByPrimaryKeySelective(resource);
    }

    /**
     * 删除资源
     *
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteResourceById(Long id) {
        CmResource cmResource = cmResourceMapper.selectByPrimaryKey(id);
        CmResourceUrlExample example = new CmResourceUrlExample();
        CmResourceUrlExample.Criteria criteria = example.createCriteria();
        criteria.andResIdEqualTo(cmResource.getResId());
        cmResourceUrlMapper.deleteByExample(example);
        cmResourceMapper.deleteByPrimaryKey(id);
    }
}
